#include "usb_port.h"
#include "bsp_usb.h"
#include "loger.h"
#if (CONFIG_HAL_USB_DEVICE_MODULE_ENABLED)
#include "usbd_core.h"
#endif

/* define */
#define TAG "USB-PORT"

/* static var */
#if (CONFIG_HAL_USB_DEVICE_MODULE_ENABLED)
static USBD_HandleTypeDef usb_device_handle_t;
#endif



/* func common */

void usb_port_hw_init(void)
{
    bsp_usb_init();
}

/* func inner */

USBD_HandleTypeDef *usbd_get_handle(void)
{
    return &usb_device_handle_t;
}



/* func - usbd msc */

#if (CONFIG_HAL_USB_DEVICE_CLASS_MSC_ENABLE)
#include "usbd_msc.h"

extern USBD_DescriptorsTypeDef usbd_msc_desc_t;
extern USBD_StorageTypeDef usbd_msc_fops_t;

void usbd_msc_init(void)
{
    USBD_Init(&usb_device_handle_t, &usbd_msc_desc_t, 0);
    USBD_RegisterClass(&usb_device_handle_t, USBD_MSC_CLASS);
    USBD_MSC_RegisterStorage(&usb_device_handle_t, &usbd_msc_fops_t);
    USBD_Start(&usb_device_handle_t);
    LOG_I(TAG, "usbd-msc init");
}

void usbd_msc_deinit(void)
{
    USBD_Stop(&usb_device_handle_t);
    USBD_DeInit(&usb_device_handle_t);
    LOG_I(TAG, "usbd-msc deinit");
}

#endif


#if (CONFIG_HAL_USB_DEVICE_CLASS_HID_CUSTOM_ENABLE)
#include "usbd_hid_custom.h"

extern USBD_DescriptorsTypeDef USBD_HID_Custom_Desc;
extern USBD_ClassTypeDef USBD_HID_Custom_Class;
extern USBD_HID_CUSTOM_ItfTypeDef USBD_HID_Custom_fops;

extern void (*usbd_hid_rx02_handle)(uint8_t *data, const uint8_t len);
extern void (*usbd_hid_rx04_handle)(uint8_t *data, const uint8_t len);
static uint8_t usbd_hid_custom_tx_buff[65];


void usbd_hid_custom_init(void)
{
    /* Init Device Library */
    USBD_Init(&usb_device_handle_t, &USBD_HID_Custom_Desc, 0);

    /* Add Supported Class */
    USBD_RegisterClass(&usb_device_handle_t, &USBD_HID_Custom_Class);

    /* Add Custom HID callbacks */
    USBD_HID_CUSTOM_RegisterInterface(&usb_device_handle_t, &USBD_HID_Custom_fops);

    /* Start Device Process */
    USBD_Start(&usb_device_handle_t);

    LOG_I(TAG, "usbd-hid-custom init");
}

void usbd_hid_custom_stop(void)
{
    USBD_Stop(&usb_device_handle_t);
}

/**
 * @brief USB HID Custom发送数据
 * 
 * @param id report id
 * @param data 数据指针
 * @param len 数据长度(不包括id)
 * @return uint8_t 
 */
uint8_t usbd_hid_custom_send_data(uint8_t id, uint8_t *data, uint8_t len)
{
    uint8_t res;
    uint8_t i;

    memset(usbd_hid_custom_tx_buff, 0x00, 65);
    if (len > 64) len = 64;
    usbd_hid_custom_tx_buff[0] = id;
    for (i = 0; i < len; i++)
    {
        usbd_hid_custom_tx_buff[i + 1] = data[i];
    }
    res = USBD_HID_CUSTOM_SendReport(&usb_device_handle_t, (uint8_t *)usbd_hid_custom_tx_buff, len + 1);
    return res;
}

// 设置端点02接收处理函数
void usbd_hid_custom_set_rx02_handle(void (*func)(uint8_t *data, const uint8_t len))
{
    usbd_hid_rx02_handle = func;
}

// 设置端点04接收处理函数
void usbd_hid_custom_set_rx04_handle(void (*func)(uint8_t *data, const uint8_t len))
{
    usbd_hid_rx04_handle = func;
}

#endif


#if (CONFIG_HAL_USB_DEVICE_CLASS_CDC_ENABLE)
#include "./usbd_cdc_vcp/usbd_cdc_vcp.h"

extern void (*usbd_cdc_rx_handle)(uint8_t *data, const uint32_t len);


void usbd_cdc_vcp_init(void)
{
    USBD_Init(&usb_device_handle_t, &USBD_CDC_VCP_Desc, 0);
    USBD_RegisterClass(&usb_device_handle_t, &USBD_CDC_Class);
    USBD_CDC_RegisterInterface(&usb_device_handle_t, &USBD_CDC_VCP_fops);
    USBD_Start(&usb_device_handle_t);

    LOG_I(TAG, "usbd-cdc-vcp init");

    // usbd_cdc_vcp_set_rx_handle(cdc_rx_test);
}

void usbd_cdc_vcp_stop(void)
{
    USBD_Stop(&usb_device_handle_t);
}

void usbd_cdc_vcp_set_rx_handle(void (*func)(uint8_t *data, const uint32_t len))
{
	usbd_cdc_rx_handle = func;
}

uint8_t usbd_cdc_vcp_send_data(uint8_t *data, uint32_t len)
{
	usbd_vcp_send_data(data, len);
	return 0;
}

#if 0
#include "shell.h"

void cdc_rx_test(uint8_t *data, const uint32_t len)
{
    LOG_D("CDC-RX", "%s", data);
}

int cdc_send(int argc, char **argv)
{
    const char *tx_buf = "usb device cdc test\r\n";
    char *pdata = NULL;
    int len;

    if (argc == 1)
    {
        pdata = (char*)tx_buf;
    }
    else if (argc == 2)
    {
        pdata = argv[1];
    }
    else
    {
        return -1;
    }

    len = strlen(pdata);
    if (len > 64) len = 64;

    usbd_cdc_vcp_send_data((uint8_t*)pdata, len);

    return 0;
}
SHELL_CMD_EXPORT(cdc_send, cdc_send);
#endif

#endif




